use std::cmp::Ordering;
use std::collections::HashSet;

use crate::svd::fraction::{Fraction, ToFraction};
use crate::svd::operator::FractionResult;

pub fn start_24(v:Vec<i32>, target: i32) -> Vec<String> {
    if v.len()<2{
        return  vec![String::from("请填写至少两个数字")]
    }
    let vec = v.iter()
        .map(|x| x.f())
        .collect();
    let mut vvs: Vec<Vec<FractionResult>> = Vec::new();
    let mut vs: Vec<FractionResult> = Vec::new();
    let mut set: HashSet<Vec<FractionResult>> = HashSet::new();
    let res_set = cal(vec, target.f(), &mut vs, &mut set, &mut vvs);
    let mut return_str = Vec::new();
    if res_set.is_empty() {
        return_str.push(String::from("没有成功的点数"));
        return return_str;
    }
    let mut set = HashSet::new();
    for i in res_set {
        let res: String = FractionResult::print_fraction_result(i);
        if set.insert(res.clone()) {
            return_str.push(res);
        }
    }
    return_str
}

fn cal<'a>(
    v: Vec<Fraction>,
    t: Fraction,
    vs: &'a mut Vec<FractionResult>,
    set: &'a mut HashSet<Vec<FractionResult>>,
    vvs: &'a mut Vec<Vec<FractionResult>>,
) -> &'a Vec<Vec<FractionResult>> {
    for i in 0..v.len() - 1 {
        for j in i + 1..v.len() {
            let vec: Vec<FractionResult> = FractionResult::cal(v[i], v[j]);
            match v.len().cmp(&(2_usize)) {
                Ordering::Less => {}
                Ordering::Equal => {
                    for k in vec {
                        vs.push(k.clone());
                        if k.fraction == t {
                            if set.insert(vs.clone()) {
                                vvs.push(vs.clone())
                            };
                        }
                        vs.pop();//弹出最后一个元素
                    }
                }
                Ordering::Greater => {
                    for k in vec {
                        vs.push(k.clone());
                        let nv = v.mer(i, j, k.fraction);
                        cal(nv, t, vs, set, vvs);
                        vs.pop();
                    }
                }
            }
        }
    }
    vvs
}

pub trait Merge2To1<T> {
    fn mer(&self, first: usize, sec: usize, t: T) -> Vec<T>;
}

impl<T> Merge2To1<T> for Vec<T>
    where T: Clone {
    fn mer(&self, fst: usize, snd: usize, t: T) -> Vec<T> {
        let mut vec = Vec::new();
        for item in self.iter().enumerate() {
            if item.0 == fst {
                vec.push(t.clone());
            } else if item.0 == snd {} else { vec.push(item.1.clone()) }
        }
        vec
    }
}

